#include <iostream>
#include <string>
#include <vector>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>

#include "task.hpp"

const int PROCESS_NUM = 5; // 进程数

void distributeTask(int who, int fd, uint32_t command)
{
    // 将command写入到fd中
    write(fd, &command, sizeof(uint32_t));  
    std::cout << "ChildProcess Id:" << who << "  fd:" << fd << "  command:" << command << std::endl;
}

uint32_t waitCommand(int fd)
{
    int command = 0;
    ssize_t n = read(fd, &command, sizeof(uint32_t));
    assert(n == sizeof(uint32_t));
    return command;
}

// 进程池
int main()
{
    Load(); // 载入任务

    //std::cout << handlerSize() << std::endl;
    //show();

    // 创建子进程
    std::vector<std::pair<pid_t, int>> slot; // 记录子进程pid和对应的文件描述符

    // 循环创建子进程
    for (int i = 0; i < PROCESS_NUM; ++i)
    {
        // 创建管道
        int pipefd[2] = {0};
        int n = pipe(pipefd); // 调用管道创建接口

        if (n == -1) // 检查管道是否成功创建
        {
            perror("pipe");
            exit(1);
        }

        pid_t id = fork();
        if (id < 0)
        {
            // 子进程创建失败
            perror("fork");
            exit(1);
        }
        else if (id == 0) // 子进程代码（执行指令）
        {
            // 关闭不需要的文件描述符
            //std::cout << pipefd[0] << std::endl;
            close(pipefd[1]);

            while(true)
            {
                //等待子进程
                uint32_t command = waitCommand(pipefd[0]);   //阻塞等待指令
                trace_back[command](); 
            }

            close(pipefd[0]);
            exit(0);
        }

        // 关闭父进程不需要的fd
        close(pipefd[0]);
        slot.emplace_back(id, pipefd[1]);
    }

    srand((unsigned int)time(NULL));    //保证数据生成的随机性

    // 父进程向子进程派发任务
    while (true)
    {
        std::cout << "##########################################" << std::endl;
        std::cout << "###   1.show task  2.distribute task   ###" << std::endl;
        std::cout << "##########################################" << std::endl;

        std::cout << "please choice: > ";
        int choice = 0;
        std::cin >> choice;    // 输入用户选择

        if(choice == 1)
        {
            show();
        }
        else if(choice == 2)
        {
            int command = 0;
            
            std::cout << "please input command: > ";
            std::cin >> command;    

            if(command >= 0 && command < handlerSize()) 
            {
                int proc = rand() % slot.size();   //选择进程
                distributeTask(slot[proc].first, slot[proc].second, command);   //派发任务
            }
            else
            {
                std::cout << "input error command" << std::endl;
            }
        }
        else
        {
            std::cout << "error input" << std::endl;
        }

        usleep(10000);
    }

    // 关闭文件描述符
    for(const auto& s : slot)
    {
        close(s.second);
    }

    // 阻塞等待子进程，回收资源
    for(const auto& s : slot)
    {
        waitpid(s.first, NULL, 0);
    }

    return 0;
}